package wymiana.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import wymiana.domain.BaseEntity;


public class GenericDao<E extends BaseEntity> extends HibernateDaoSupport {

    private Class<E> entityClass;

    protected GenericDao(Class<E> entityClass, SessionFactory sf) {
        setSessionFactory(sf);
        this.entityClass = entityClass;
    }

	public E getById(Serializable id) {
        return (E)getHibernateTemplate().get(entityClass, id);
    }

    public List<E> getAll() {
        return getHibernateTemplate().loadAll(entityClass);
    }

    public void delete(E entity) {
        getHibernateTemplate().delete(entity);
    }

    public void save(E entity) {
        getHibernateTemplate().save(entity);
    }

    public void update(E entity) {
        getHibernateTemplate().update(entity);
    }

    public void saveOrUpdate(E entity) {
        getHibernateTemplate().saveOrUpdate(entity);
    }

    public E merge(E entity) {
        return (E) getHibernateTemplate().merge(entity);
    }

    @SuppressWarnings("unchecked")
    protected E findFirst(final String hql, final Object[] parameters) {
        // we need separate instance of HibernateTemplate
        HibernateTemplate ht = new HibernateTemplate(getSessionFactory());
        ht.setMaxResults(1);
        List<E> list = (List<E>) ht.find(hql, parameters);
        if (list.size() == 0) return null;
        return list.get(0);
    }
    
    protected boolean exists(final Class<E> clazz, final String idField, final Object idValue) {
        return getHibernateTemplate().executeWithNativeSession(new HibernateCallback<Boolean>() {
            @Override
            public Boolean doInHibernate(Session session) throws HibernateException, SQLException {
                Query query = session.createQuery(
                        "select 1 from " + clazz.getSimpleName() + " where " + idField + "=?");
                query.setParameter(0, idValue);
                return query.uniqueResult() != null;
            }
        });
    }
}
